"""
报告生成器模块
生成HTML、PDF、Excel格式的测试报告
"""

import os
import json
from typing import Dict, List, Any
from datetime import datetime
from jinja2 import Template
import pandas as pd


class ReportGenerator:
    """报告生成器"""
    
    def __init__(self, template_dir: str = None):
        """
        初始化报告生成器
        
        Args:
            template_dir: 模板目录路径
        """
        self.template_dir = template_dir or os.path.join(
            os.path.dirname(os.path.dirname(__file__)), 'templates'
        )
    
    def build_report_data(self, project_name: str, test_results: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        构建报告数据
        
        Args:
            project_name: 项目名称
            test_results: 测试结果列表
            
        Returns:
            报告数据字典
        """
        total_executions = len(test_results)
        success_count = sum(1 for r in test_results if r.get('result') == 'success')
        failed_count = total_executions - success_count
        pass_rate = (success_count / total_executions * 100) if total_executions > 0 else 0
        
        # 计算响应时间统计
        response_times = [r.get('response_time', 0) for r in test_results if r.get('response_time')]
        avg_response_time = sum(response_times) / len(response_times) if response_times else 0
        max_response_time = max(response_times) if response_times else 0
        min_response_time = min(response_times) if response_times else 0
        
        # 按用例分组统计
        case_stats = {}
        for result in test_results:
            case_id = result.get('case_id')
            if case_id not in case_stats:
                case_stats[case_id] = {
                    'case_name': result.get('case_name'),
                    'total': 0,
                    'success': 0,
                    'failed': 0,
                    'results': []
                }
            
            case_stats[case_id]['total'] += 1
            if result.get('result') == 'success':
                case_stats[case_id]['success'] += 1
            else:
                case_stats[case_id]['failed'] += 1
            
            case_stats[case_id]['results'].append(result)
        
        report_data = {
            'project_name': project_name,
            'generate_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'summary': {
                'total_cases': len(case_stats),
                'total_executions': total_executions,
                'success_count': success_count,
                'failed_count': failed_count,
                'pass_rate': round(pass_rate, 2),
                'avg_response_time': round(avg_response_time, 2),
                'max_response_time': max_response_time,
                'min_response_time': min_response_time
            },
            'case_stats': case_stats,
            'test_results': test_results
        }
        
        return report_data
    
    def generate_html_report(self, report_data: Dict[str, Any], output_path: str) -> str:
        """
        生成HTML报告
        
        Args:
            report_data: 报告数据
            output_path: 输出文件路径
            
        Returns:
            生成的HTML文件路径
        """
        # HTML模板
        html_template = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API测试报告 - {{ project_name }}</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Microsoft YaHei', Arial, sans-serif; background: #f5f5f5; padding: 20px; }
        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h1 { color: #333; margin-bottom: 10px; }
        .subtitle { color: #666; margin-bottom: 30px; }
        .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
        .summary-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; }
        .summary-card.success { background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%); }
        .summary-card.failed { background: linear-gradient(135deg, #eb3349 0%, #f45c43 100%); }
        .summary-card.rate { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); }
        .summary-card h3 { font-size: 14px; margin-bottom: 10px; opacity: 0.9; }
        .summary-card .value { font-size: 32px; font-weight: bold; }
        .case-list { margin-top: 30px; }
        .case-item { background: #fafafa; padding: 15px; margin-bottom: 15px; border-radius: 6px; border-left: 4px solid #667eea; }
        .case-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
        .case-name { font-size: 16px; font-weight: bold; color: #333; }
        .badge { padding: 4px 12px; border-radius: 12px; font-size: 12px; font-weight: bold; }
        .badge.success { background: #d4edda; color: #155724; }
        .badge.failed { background: #f8d7da; color: #721c24; }
        table { width: 100%; border-collapse: collapse; margin-top: 10px; }
        th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
        th { background: #f8f9fa; font-weight: bold; color: #333; }
        .details { background: #f8f9fa; padding: 10px; border-radius: 4px; margin-top: 10px; font-size: 12px; max-height: 300px; overflow-y: auto; }
        .details pre { white-space: pre-wrap; word-wrap: break-word; }
        .collapsible { cursor: pointer; color: #667eea; text-decoration: underline; }
        .hidden { display: none; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🚀 API测试报告</h1>
        <div class="subtitle">项目: {{ project_name }} | 生成时间: {{ generate_time }}</div>
        
        <div class="summary">
            <div class="summary-card">
                <h3>总执行次数</h3>
                <div class="value">{{ summary.total_executions }}</div>
            </div>
            <div class="summary-card success">
                <h3>成功次数</h3>
                <div class="value">{{ summary.success_count }}</div>
            </div>
            <div class="summary-card failed">
                <h3>失败次数</h3>
                <div class="value">{{ summary.failed_count }}</div>
            </div>
            <div class="summary-card rate">
                <h3>通过率</h3>
                <div class="value">{{ summary.pass_rate }}%</div>
            </div>
        </div>
        
        <div class="case-list">
            <h2>📋 用例执行详情</h2>
            {% for case_id, case_stat in case_stats.items() %}
            <div class="case-item">
                <div class="case-header">
                    <div class="case-name">{{ case_stat.case_name }}</div>
                    <span class="badge {{ 'success' if case_stat.failed == 0 else 'failed' }}">
                        {{ case_stat.success }}/{{ case_stat.total }} 通过
                    </span>
                </div>
                
                <table>
                    <thead>
                        <tr>
                            <th>数据ID</th>
                            <th>执行时间</th>
                            <th>响应时间</th>
                            <th>状态</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for result in case_stat.results %}
                        <tr>
                            <td>{{ result.data_id or '-' }}</td>
                            <td>{{ result.execute_time }}</td>
                            <td>{{ result.response_time }}ms</td>
                            <td><span class="badge {{ result.result }}">{{ result.result }}</span></td>
                            <td><span class="collapsible" onclick="toggleDetails('detail_{{ loop.index0 }}')">查看详情</span></td>
                        </tr>
                        <tr id="detail_{{ loop.index0 }}" class="hidden">
                            <td colspan="5">
                                <div class="details">
                                    <strong>请求:</strong>
                                    <pre>{{ result.request_detail | tojson(indent=2) }}</pre>
                                    <strong>响应:</strong>
                                    <pre>{{ result.response_detail | tojson(indent=2) }}</pre>
                                    {% if result.error_msg %}
                                    <strong>错误信息:</strong>
                                    <pre>{{ result.error_msg }}</pre>
                                    {% endif %}
                                </div>
                            </td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
            {% endfor %}
        </div>
    </div>
    
    <script>
        function toggleDetails(id) {
            var element = document.getElementById(id);
            element.classList.toggle('hidden');
        }
    </script>
</body>
</html>
        """
        
        # 渲染模板
        template = Template(html_template)
        html_content = template.render(**report_data)
        
        # 确保输出目录存在
        os.makedirs(os.path.dirname(output_path), exist_ok=True)
        
        # 写入文件
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        
        return output_path
    
    def generate_excel_report(self, report_data: Dict[str, Any], output_path: str) -> str:
        """
        生成Excel报告
        
        Args:
            report_data: 报告数据
            output_path: 输出文件路径
            
        Returns:
            生成的Excel文件路径
        """
        # 确保输出目录存在
        os.makedirs(os.path.dirname(output_path), exist_ok=True)
        
        with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
            # Sheet1: 执行详情
            results_data = []
            for result in report_data['test_results']:
                results_data.append({
                    '用例ID': result.get('case_id'),
                    '用例名称': result.get('case_name'),
                    '数据ID': result.get('data_id', '-'),
                    '执行时间': result.get('execute_time'),
                    '响应时间(ms)': result.get('response_time'),
                    '执行结果': result.get('result'),
                    '错误信息': result.get('error_msg', '-')
                })
            
            df_results = pd.DataFrame(results_data)
            df_results.to_excel(writer, sheet_name='执行详情', index=False)
            
            # Sheet2: 统计汇总
            summary = report_data['summary']
            summary_data = [
                ['项目名称', report_data['project_name']],
                ['生成时间', report_data['generate_time']],
                ['总用例数', summary['total_cases']],
                ['总执行次数', summary['total_executions']],
                ['成功次数', summary['success_count']],
                ['失败次数', summary['failed_count']],
                ['通过率(%)', summary['pass_rate']],
                ['平均响应时间(ms)', summary['avg_response_time']],
                ['最大响应时间(ms)', summary['max_response_time']],
                ['最小响应时间(ms)', summary['min_response_time']]
            ]
            
            df_summary = pd.DataFrame(summary_data, columns=['指标', '值'])
            df_summary.to_excel(writer, sheet_name='统计汇总', index=False)
        
        return output_path
    
    def generate_pdf_report(self, html_path: str, output_path: str) -> str:
        """
        生成PDF报告（从HTML转换）
        
        Args:
            html_path: HTML文件路径
            output_path: 输出PDF文件路径
            
        Returns:
            生成的PDF文件路径
        """
        try:
            import pdfkit
            
            # 确保输出目录存在
            os.makedirs(os.path.dirname(output_path), exist_ok=True)
            
            # 配置选项
            options = {
                'page-size': 'A4',
                'margin-top': '0.75in',
                'margin-right': '0.75in',
                'margin-bottom': '0.75in',
                'margin-left': '0.75in',
                'encoding': 'UTF-8',
                'no-outline': None
            }
            
            # 转换为PDF
            pdfkit.from_file(html_path, output_path, options=options)
            
            return output_path
            
        except Exception as e:
            raise Exception(f"PDF生成失败: {str(e)}. 请确保已安装wkhtmltopdf")
